package com.apache.flow.web;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import net.sf.json.JSONObject;

import org.apache.struts2.convention.annotation.Namespace;
import org.apache.struts2.convention.annotation.Result;
import org.apache.struts2.convention.annotation.Results;
import org.jbpm.api.Execution;
import org.jbpm.api.ExecutionService;
import org.jbpm.api.HistoryService;
import org.jbpm.api.ProcessEngine;
import org.jbpm.api.RepositoryService;
import org.jbpm.api.TaskService;
import org.jbpm.api.history.HistoryProcessInstanceQuery;
import org.jbpm.api.task.Task;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;

import com.apache.common.FlowBaseAction;
import com.apache.core.utils.web.struts2.Struts2Utils;
import com.apache.flow.core.entity.FlowDeploy;
import com.apache.flow.core.manager.FlowDeployManager;
import com.apache.flow.core.manager.FlowHistoryManager;
import com.apache.flow.taskHandler.ZbxTask;
import com.apache.flow.vo.TaskVo;
import com.apache.tools.DateUtils;
import com.apache.tools.NumberUtils;
import com.apache.tools.StrUtil;

@Namespace("/flow/core")
@Results({ @Result(name = "toApprove", location = "../test/test-flow-approve.jsp") })
public class FlowTestAction extends FlowBaseAction {
	private static final long serialVersionUID = 1L;

	/**
	 * 日志
	 */
	private Logger logger = LoggerFactory.getLogger(FlowTestAction.class);

	/**
	 * 流程引擎
	 */
	@Autowired
	private ProcessEngine processEngine;
	/**
	 * 流程定义key
	 */
	private String processDefinitionKey;
	/**
	 * 流程定义id
	 */
	private String definitionId;
	private String rows;
	private String page;
	/**
	 * 任务id
	 */
	private String taskId;
	private String approve;
	private String processInstanceId;

	private RepositoryService repositoryService;

	@Autowired
	private FlowDeployManager flowDeployManager;
	@Autowired
	private FlowHistoryManager flowHistoryManager;

	/**
	 * 
	 * @return
	 * @throws IOException
	 * <p>@description 执行任务
	 * <p>@version 1.0
	 * <p>@author lvcai
	 * <p>@update 2013-7-29 下午06:18:29
	 */
	public String executeFlow() throws IOException {
		try {
			TaskService taskService = processEngine.getTaskService();
			Map<String, String> variables = new HashMap<String, String>();
			Enumeration<String> names = Struts2Utils.getRequest().getParameterNames();
			while (names.hasMoreElements()) {
				String key = names.nextElement();
				variables.put(key, Struts2Utils.getRequest().getParameter(key));
			}
			//用来查看传递过来的值
			Set<Entry<String, String>> set = variables.entrySet();
			if (taskId != null) {
				//String dayNum = (String)WorkflowUtil.getProcessInstanceParamsValue(Struts2Utils.getSession(), taskId, "dayNum");
				//				if(dayNum != null && !variables.containsKey("dayNum"))
				//					variables.put("dayNum", dayNum);
			}
			//如果没有指定expr跳转条件而直接通过transition的名称决定流程跳转时需要传递approve参数
			if (approve != null)
				taskService.completeTask(taskId, approve, variables);
			else
				taskService.completeTask(taskId, variables);
			showOk("任务执行成功！");
		} catch (Exception e) {
			showError("任务执行失败！");
			e.printStackTrace();
		}
		return null;
	}

	/**
	 * 启动流程实例
	 * <p>启动流程实例应该在业务系统中执行<p>
	 * @return String
	 * @throws IOException 
	 */
	public String start() throws IOException {
		//管理流程实例
		try {
			ExecutionService executionService = processEngine.getExecutionService();
			Map<String, String> variables = new HashMap<String, String>();
			Enumeration<String> names = Struts2Utils.getRequest().getParameterNames();
			while (names.hasMoreElements()) {
				String key = names.nextElement();
				variables.put(key, Struts2Utils.getRequest().getParameter(key));
			}
			executionService.startProcessInstanceById(definitionId, variables);
			showOk("启动流程成功！");
		} catch (Exception e) {
			logger.debug("启动" + definitionId + "的流程实例错误");
			showError("启动流程失败！");
			e.printStackTrace();
		}

		return null;
	}

	/**
	 * 某个人任务列表
	 * @return String
	 */
	public String taskPersonData() {
		int pageNo = NumberUtils.getInt(page, 1);
		int pageSize = NumberUtils.getInt(rows, 15);
		int startIndex = (pageNo - 1) * pageSize;

		TaskService taskService = processEngine.getTaskService();
		String taskAssignee = Struts2Utils.getRequest().getParameter("taskAssignee");
		JSONObject json = new JSONObject();
		if (taskAssignee != null) {
			List<Task> taskList = taskService.findPersonalTasks(taskAssignee);
			List<Task> list = taskService.findGroupTasks(taskAssignee);
			taskList = taskList == null ? list : taskList;

			if (list != null && taskList != null)
				taskList.addAll(list);

			int sumCount = taskList.size();

			List<TaskVo> taskVoList = new ArrayList<TaskVo>();
			for (Task task : taskList) {
				TaskVo taskVo = new TaskVo();
				taskVo.setId(task.getId());
				taskVo.setName(task.getName());
				taskVo.setActivityName(task.getActivityName());
				taskVo.setFormResourceName(task.getFormResourceName());
				taskVo.setDescription(task.getDescription());
				taskVo.setAssignee(task.getAssignee());
				taskVo.setExecutionId(task.getExecutionId());
				taskVo.setCreateTime(DateUtils.format(task.getCreateTime(), DateUtils.FmtStr.yyyyMMdd_HHmmss.toString()));

				taskVoList.add(taskVo);
			}
			json.put("total", taskVoList.size());
			json.put("rows", taskVoList);

		} else {
			json.put("total", 0);
			json.put("rows", null);
		}
		try {
			Struts2Utils.getResponse().getWriter().write(json.toString());
		} catch (IOException e) {
			logger.debug("得到流程定义数据错误" + e);
			e.printStackTrace();
		}
		return null;
	}

	/**
	 * 某个组任务列表
	 * 目前不做
	 * @return String
	 */
	public String taskGroupData() {
		TaskService taskService = processEngine.getTaskService();
		String group = Struts2Utils.getRequest().getParameter("group");
		List<Task> taskList = taskService.findGroupTasks(group);
		return null;
	}

	/**
	 * description: 跳转到审核页面 
	 */
	public String toApprove() {
		return "toApprove";
	}

	/**
	 * 
	 * @return
	 * @throws IOException
	 * <p>@description 流程审核方法
	 * <p>@version 1.0
	 * <p>@author lvcai
	 * <p>@update 2013-7-29 下午06:06:36
	 */
	public String approve() throws IOException {
		logger.info("流程审核方法开始执行");
		JSONObject jobj = new JSONObject();
		String returnResult = null;
		String errmsg = null;
		String instFlag = "F";

		Map<String, String> variables = new HashMap<String, String>();
		Enumeration<String> names = Struts2Utils.getRequest().getParameterNames();
		while (names.hasMoreElements()) {
			String key = names.nextElement();
			if (null != key && !"".equals(key)) {
				String value = Struts2Utils.getRequest().getParameter(key);
				variables.put(key, java.net.URLDecoder.decode(value, "UTF-8"));
			}
		}
		String executeTime = variables.get("executeTime");//---
		if (StrUtil.isNull(executeTime))
			executeTime = "";//---
		String taskId = variables.get("taskId");
		String result = variables.get("result");
		logger.info("流程审核：获取到taskId=" + taskId + "  result=" + result);
		String taskName = "";
		if (null != taskId && !"".equals(taskId) && null != result && !"".equals(result)) {
			try {
				TaskService taskService = processEngine.getTaskService();
				Task task = taskService.getTask(taskId);
				taskName = task.getName();
				if (task != null) {

					String exeId = task.getExecutionId();
					ExecutionService executionService = processEngine.getExecutionService();
					Execution execution = executionService.findExecutionById(exeId);
					executionService.setVariable(exeId, "executeTime", executeTime);//---
					Execution processInstance = execution.getProcessInstance();
					String processInstanceId = processInstance.getId();

					ZbxTask sign = new ZbxTask(task, variables);
					processEngine.execute(sign);

					HistoryService historyService = processEngine.getHistoryService();
					HistoryProcessInstanceQuery historyProcessInstanceQuery = historyService
							.createHistoryProcessInstanceQuery();
					if ("ended".equals(historyProcessInstanceQuery.processInstanceId(processInstanceId).list().get(0)
							.getState())) {
						instFlag = "T";//流程结束
					}
					returnResult = "T";
					errmsg = "流程审核成功";
					jobj.put("flag", returnResult);
					jobj.put("msg", errmsg);
				} else {
					returnResult = "F";
					errmsg = "没有找到任务Id为" + taskId + "的任务";
					jobj.put("flag", returnResult);
					jobj.put("msg", errmsg);
				}

			} catch (org.jbpm.api.JbpmException e) {
				//流程定义返回错误信息
				returnResult = "F";
				jobj.put("flag", returnResult);
				if (e.getMessage().contains("没有找到用户")) {
					errmsg = "下一任务节点没有执行用户";
					Struts2Utils.getRequest().setAttribute("info", "下个任务节点未找到任务执行者");
					jobj.put("msg", errmsg);
				} else if (e.getMessage().contains("suspended")) {
					errmsg = "该流程已挂起";
					Struts2Utils.getRequest().setAttribute("info", "该流程已挂起");
					jobj.put("msg", errmsg);
				} else {
					errmsg = "流程审核时发送未知异常";
					jobj.put("msg", errmsg);
				}
				e.printStackTrace();
			} catch (Exception e) {
				returnResult = "F";
				errmsg = "流程审核时发送未知异常";
				e.printStackTrace();
				jobj.put("flag", returnResult);
				jobj.put("msg", errmsg);
			}
		} else {
			returnResult = "F";
			errmsg = "参数taskId或result参数未传递";
			jobj.put("flag", returnResult);
			jobj.put("msg", errmsg);
		}

		Struts2Utils.getResponse().getWriter().print(jobj.toString());
		return null;
	}

	/**
	 * description:级联删除jbpm流程定义
	 * @update 2016-1-22
	 */
	public String casDelJbpmDeploy(String deploymentId) throws IOException {
		JSONObject jobj = new JSONObject();
		if (StrUtil.isNull(deploymentId)) {
			jobj.put("flag", "F");
			jobj.put("msg", "流程id(DBID)不能为空");
			Struts2Utils.getResponse().getWriter().print(jobj.toString());
			return null;
		}
		repositoryService = processEngine.getRepositoryService();
		repositoryService.deleteDeploymentCascade(deploymentId);
		jobj.put("flag", "T");
		jobj.put("msg", "级联流程定义删除成功!");
		Struts2Utils.getResponse().getWriter().print(jobj.toString());
		return null;
	}

	/**
	 * description: 删除flow_deploy表中 的数据deployId 
	 * @param deployId
	 * @update 2016-1-22
	 */
	public String delFlowDeploy(String deployId) throws IOException {
		JSONObject jobj = new JSONObject();
		if (StrUtil.isNull(deployId)) {
			jobj.put("flag", "F");
			jobj.put("msg", "流程id(DBID)不能为空");
			Struts2Utils.getResponse().getWriter().print(jobj.toString());
			return null;
		}
		FlowDeploy flowDeploy = flowDeployManager.getById(deployId);
		if (flowDeploy == null) {
			jobj.put("flag", "F");
			jobj.put("msg", "没有查到要删除的数据！");
			Struts2Utils.getResponse().getWriter().print(jobj.toString());
			return null;
		}

		flowDeployManager.delete(flowDeploy);

		jobj.put("flag", "T");
		jobj.put("msg", "删除成功！");
		Struts2Utils.getResponse().getWriter().print(jobj.toString());
		return null;
	}

	/**
	 * 删除流程实例(jbpm)
	 * @return String
	 * @throws IOException 
	 */
	public String delJbpmPro() throws IOException {
		JSONObject jobj = new JSONObject();
		if (StrUtil.isNull(processInstanceId)) {
			jobj.put("flag", "F");
			jobj.put("msg", "流程实例id不能为空");
			Struts2Utils.getResponse().getWriter().print(jobj.toString());
			return null;
		}
		try {
			logger.info("删除流程实例  processInstanceId=" + processInstanceId);

			ExecutionService executionService = processEngine.getExecutionService();
			//executionService.deleteProcessInstance(processInstanceId);
			//删除实例，包含历史数据
			executionService.deleteProcessInstanceCascade(processInstanceId);
			showOk("删除流程实例成功！");
		} catch (Exception e) {
			logger.debug("删除流程实例" + processInstanceId + "失败！" + e);
			showError("删除流程实例失败！");
			e.printStackTrace();
		}
		return null;
	}

	/**
	 * 删除历史数据流程实例
	 * @return String
	 * @throws IOException 
	 */
	public String delHisFlowPro() throws IOException {
		JSONObject jobj = new JSONObject();
		if (StrUtil.isNull(processInstanceId)) {
			jobj.put("flag", "F");
			jobj.put("msg", "流程实例id不能为空");
			Struts2Utils.getResponse().getWriter().print(jobj.toString());
			return null;
		}
		try {
			logger.info("删除历史数据流程实例  processInstanceId=" + processInstanceId);
			int delResult = flowHistoryManager.delFlowHistoryById(processInstanceId);

			if (delResult > 0) {
				logger.info("---------删除历史数据成功！delete{" + delResult + "}rows！");
				//删除历史数据成功
				showOk("删除历史数据成功！");
			} else {
				showError("未找到要删除的数据！");
			}
		} catch (Exception e) {
			logger.debug("删除历史数据" + processInstanceId + "失败！" + e);
			showError("删除历史数据失败！");
			e.printStackTrace();
		}
		return null;
	}

	public String getProcessDefinitionKey() {
		return processDefinitionKey;
	}

	public void setProcessDefinitionKey(String processDefinitionKey) {
		this.processDefinitionKey = processDefinitionKey;
	}

	public String getDefinitionId() {
		return definitionId;
	}

	public void setDefinitionId(String definitionId) {
		this.definitionId = definitionId;
	}

	public String getTaskId() {
		return taskId;
	}

	public void setTaskId(String taskId) {
		this.taskId = taskId;
	}

	public String getApprove() {
		return approve;
	}

	public void setApprove(String approve) {
		this.approve = approve;
	}

	public String getRows() {
		return rows;
	}

	public void setRows(String rows) {
		this.rows = rows;
	}

	public String getPage() {
		return page;
	}

	public void setPage(String page) {
		this.page = page;
	}

	public String getProcessInstanceId() {
		return processInstanceId;
	}

	public void setProcessInstanceId(String processInstanceId) {
		this.processInstanceId = processInstanceId;
	}

	public RepositoryService getRepositoryService() {
		return repositoryService;
	}

	public void setRepositoryService(RepositoryService repositoryService) {
		this.repositoryService = repositoryService;
	}

}
